package encrypt

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
)

// RSAGenerateKey 生成rsa密钥对
func RSAGenerateKey(bits int) {

	pairKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		fmt.Println("generate rsa key err：", err.Error())
	}

	//save private key
	privateKey := x509.MarshalPKCS1PrivateKey(pairKey)

	priFile, err := os.Create("pri.pem")
	if err != nil {
		fmt.Println("create private key file err：", err.Error())
	}

	priBlock := pem.Block{Type: "RSA PRIVATE KEY", Bytes: privateKey}

	if err := pem.Encode(priFile, &priBlock); err != nil {
		fmt.Println("save private key to file err：", err.Error())
	}

	//save public key
	publicKey, _ := x509.MarshalPKIXPublicKey(&pairKey.PublicKey)

	pubFile, err := os.Create("pub.pem")
	if err != nil {
		fmt.Println("create public key file err：", err.Error())
	}

	pubBlock := pem.Block{Type: "RSA PUBLIC KEY", Bytes: publicKey}

	if err := pem.Encode(pubFile, &pubBlock); err != nil {
		fmt.Println("save public key to file err：", err.Error())
	}
}

// RSAEncrypt RSA加密
func RSAEncrypt(plainText string, path string) string {

	// 读取公钥信息
	data, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println("read pub.pem err：", err.Error())
	}

	// pem解码读取到的公钥信息
	pubBlock, _ := pem.Decode(data)

	//x509反序列化
	publicKeyInterface, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
	if err != nil {
		fmt.Println("parse public key err：", err.Error())
	}

	publicKey := publicKeyInterface.(*rsa.PublicKey)

	//公钥加密
	clipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(plainText))
	if err != nil {
		fmt.Println("encrypt plainText err：", err.Error())
	}

	return string(clipherText)
}

// RSADecode RSA解密
func RSADecrypt(clipherText string, path string) string {

	// 读取私钥信息
	data, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println("read pri key err：", err.Error())
	}

	// pem解码
	priBlock, _ := pem.Decode(data)

	//x509反序列化
	privatekey, err := x509.ParsePKCS1PrivateKey(priBlock.Bytes)
	if err != nil {
		fmt.Println("parse private key err：", err.Error())
	}

	// 私钥解密
	plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privatekey, []byte(clipherText))
	if err != nil {
		fmt.Println("decrypt clipherText err：", err.Error())
	}

	return string(plainText)
}

func TestGoRsa() {
	RSAGenerateKey(1024)
	var plainText = "hello world!"
	clipherText := RSAEncrypt(plainText, "./pub.pem")
	text := RSADecrypt(clipherText, "./pri.pem")
	if text == plainText {
		fmt.Println("rsa加解密正确")
	}
}
